#include "PostProcess.h"

PostProcess::PostProcess(const LPDIRECT3DDEVICE9 device, EffectManager *effMgr, TextureManager *texMgr) :Effect(device, effMgr, texMgr)
{
	const WORD shadowMapSize = 512;
	texMgr->makeRenderTarget(L"postProc", D3DFMT_A8R8G8B8, shadowMapSize, shadowMapSize);
	texMgr->makeRenderTarget(L"surfBuf", D3DFMT_A8R8G8B8);
	texMgr->makeRenderTarget(L"surfBuf2", D3DFMT_A8R8G8B8);
	texMgr->makeRenderTarget(L"surfBuf3", D3DFMT_A8R8G8B8);

	gaussian = new Gaussian(15);
	gaussian->setBlurParametersH(1.0f/(SCREEN_WIDTH/2.0f), 0);
	gaussian->setBlurParametersV(0, 1.0f/(SCREEN_HEIGHT/2.0f));
}

PostProcess::~PostProcess(void)
{
}

void PostProcess::blurTexture(
							  const LPDIRECT3DTEXTURE9 inputTex,
							  LPDIRECT3DSURFACE9 targetSurface,
							  ModelMesh *quad,
							  LPDIRECT3DSURFACE9 prevSurf)
{
	// Horizontal Blur
	device->SetRenderTarget(0, *texMgr->getSurface(L"surfBuf"));
	blurTexture(
		inputTex,
		gaussian->getHOffsets(),
		gaussian->getHWeights(),
		quad);

	// Vertical Blur
	device->SetRenderTarget(0, targetSurface);
	blurTexture(
		texMgr->getTexture(L"surfBuf"),
		gaussian->getVOffsets(),
		gaussian->getVWeights(),
		quad);

	device->SetRenderTarget(0, prevSurf);
}

void PostProcess::blurTexture(
							  const LPDIRECT3DTEXTURE9 blurTexture,
							  const vector<D3DXVECTOR4> sampleOffsets, 
							  const vector<float> sampleWeights,
							  ModelMesh *quad)
{
	device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f ,0);

	effMgr->setupEffect(BLUR_FX);
	effMgr->getSetEffect()->SetFloatArray("sampleWeights", &sampleWeights[0], sampleWeights.size());
	effMgr->getSetEffect()->SetVectorArray("sampleOffsets", &sampleOffsets[0], sampleOffsets.size());
	effMgr->getSetEffect()->SetTexture("depthMap", blurTexture);

	UINT numPasses;
	device->BeginScene();
	effMgr->getSetEffect()->Begin(&numPasses, 0);
	effMgr->getSetEffect()->BeginPass(0);
	quad->getMesh()->DrawSubset(0);
	effMgr->getSetEffect()->EndPass();
	effMgr->getSetEffect()->End();
	device->EndScene();
}


void PostProcess::bloom(
						const LPDIRECT3DTEXTURE9 normalTex,
						const LPDIRECT3DTEXTURE9 blurredTex,
						ModelMesh *quad,
						LPDIRECT3DSURFACE9 prevSurf)
{
	effMgr->setupEffect(GLOW_FX);
	effMgr->getSetEffect()->SetTexture("normalTex", normalTex);
	effMgr->getSetEffect()->SetTexture("blurredTex", blurredTex);
	effMgr->getSetEffect()->SetVector("halfPixel", &commonValues::halfPixel);

	UINT numPasses;
	device->BeginScene();
	effMgr->getSetEffect()->Begin(&numPasses, 0);
	effMgr->getSetEffect()->BeginPass(0);
	quad->getMesh()->DrawSubset(0);
	effMgr->getSetEffect()->EndPass();
	effMgr->getSetEffect()->End();
	device->EndScene();
}

void PostProcess::depthOfField(
							   const LPDIRECT3DTEXTURE9 normalTex,
							   const LPDIRECT3DTEXTURE9 blurredTex,
							   const LPDIRECT3DTEXTURE9 depthTex,
							   Camera* camera, ModelMesh *quad,
							   const FLOAT distance,
							   const FLOAT length,
							   LPDIRECT3DSURFACE9 prevSurf)
{
	effMgr->setupEffect(DOF_FX);

	effMgr->getSetEffect()->SetTexture("blurTexture", blurredTex);
	effMgr->getSetEffect()->SetTexture("inputTexture", normalTex);
	effMgr->getSetEffect()->SetTexture("depthTexture", depthTex);

	effMgr->getSetEffect()->SetVector("CameraPosition", &camera->getPosition4());
	effMgr->getSetEffect()->SetMatrix("InvViewProj", &camera->getInvViewProjMatrix());
	effMgr->getSetEffect()->SetVector("PixelSize", &commonValues::halfPixel);
	effMgr->getSetEffect()->SetFloat("focalDistance", distance);
	effMgr->getSetEffect()->SetFloat("focalLength", length);

	UINT numPasses;
	device->BeginScene();
	effMgr->getSetEffect()->Begin(&numPasses, 0);
	effMgr->getSetEffect()->BeginPass(0);
	quad->getMesh()->DrawSubset(0);
	effMgr->getSetEffect()->EndPass();
	effMgr->getSetEffect()->End();
	device->EndScene();
}